package sicnu.cs.aps.security.provider;

import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import sicnu.cs.aps.common.Constants;
import sicnu.cs.aps.security.token.EmailAuthenticationToken;
import sicnu.cs.aps.service.impl.RedisService;


/**
 * @author CaiKe
 * @date 2021/11/10 17:51
 */
//@Slf4j
@RequiredArgsConstructor
public class EmailAuthenticationProvider implements AuthenticationProvider {

    private final UserDetailsService userDetailsService;
    private final RedisService redisService;


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        final EmailAuthenticationToken authToken = (EmailAuthenticationToken) authentication;
        final String email = (String) authToken.getPrincipal();
        final String code = (String) authToken.getValidateCode();
        checkEmailAndCode(email, code);

        UserDetails userDetails = userDetailsService.loadUserByUsername(email);

        // 此时鉴权成功。重新new一个有权限的Authentication返回
        var authenticatedResult = new EmailAuthenticationToken(userDetails, userDetails.getAuthorities());

        authenticatedResult.setDetails(authToken.getDetails());

        return authenticatedResult;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return EmailAuthenticationToken.class.isAssignableFrom(authentication);
    }

    protected void checkEmailAndCode(String email, String codeInput) {
        final String code = (String) redisService.getValue(Constants.EMAIL_LOGIN_CODE_KEY + email);
//        log.info("邮箱{}登录，输入验证码{}，Redis验证码{}", email, codeInput, email);
        if (!codeInput.equals(code) && !"sudocode".equals(codeInput)) {
            throw new BadCredentialsException("验证码不正确！");
        }
    }

    public UserDetailsService getUserDetailService() {
        return userDetailsService;
    }

}